package com.base.component.ai.platform;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.base.component.ai.agent.bo.ContextParamBO;
import com.base.component.ai.agent.core.prompt.ExtendFillStrategy;
import com.base.component.ai.agent.core.prompt.FixedFillStrategy;
import com.base.component.ai.agent.core.prompt.FlexibleFillStrategy;
import com.base.component.ai.agent.utils.PromptUtils;
import com.gitee.magic.context.ConverterEditorUtils;
import com.gitee.magic.core.exception.ApplicationException;
import com.gitee.magic.core.json.JsonObject;
import com.gitee.magic.jdbc.persistence.source.jdbc.sqlplus.toolkit.StringUtils;

@Service
public class FillStrategyHandler<C extends ContextParamBO> {
	
	@Autowired(required = false)
	private List<FixedFillStrategy<C>> fixedFillStrategy;
	@Autowired(required = false)
	private List<FlexibleFillStrategy<C>> flexibleFillStrategy;
	@Autowired(required = false)
	private List<ExtendFillStrategy<C>> extendFillStrategy;

	/**
	 * 填充占位数据返回完整数据
	 * @param code
	 * @param prompt
	 * @param obj
	 * @return
	 */
	public <P>String fill(String code,String prompt, P obj,C context) {
		if(StringUtils.isEmpty(prompt)) {
			return null;
		}
		Map<String,Object> params=generateFillMap(code, prompt, obj, context);
		context.getPromptPlaceholder().putAll(params);
		return PromptUtils.fill(prompt, context.getPromptPlaceholder());
	}
	
	public <P>Map<String,Object> generateFillMap(String code,String prompt, P obj,C context) {
		List<String> promptFillList=PromptUtils.getPlaceholder(prompt);
		Class<?> cls=obj.getClass();
		for (Field field : cls.getDeclaredFields()) {
			if(Modifier.isFinal(field.getModifiers())||Modifier.isStatic(field.getModifiers())) {
				continue;
			}
			String fieldName = field.getName();
			if(!promptFillList.contains(fieldName)) {
				continue;
			}
			PropertyDescriptor pd=null;
			try {
				pd = new PropertyDescriptor(fieldName, cls);
			} catch (IntrospectionException e) {
				throw new ApplicationException(e);
			}
			Object o;
			try {
				o = pd.getReadMethod().invoke(obj);
			} catch (IllegalAccessException e) {
				throw new ApplicationException(e);
			} catch (IllegalArgumentException e) {
				throw new ApplicationException(e);
			} catch (InvocationTargetException e) {
				throw new ApplicationException(e);
			}
			if(o!=null) {
				continue;
			}
			//缓存已存在则跳过
			if(context.getPromptPlaceholder().containsKey(fieldName)) {
				continue;
			}
			Object v=promptInvoke(fieldName, code,context);
			if(v!=null) {
				try {
					pd.getWriteMethod().invoke(obj, v);
				} catch (IllegalAccessException e) {
					throw new ApplicationException(e);
				} catch (IllegalArgumentException e) {
					throw new ApplicationException(e);
				} catch (InvocationTargetException e) {
					throw new ApplicationException(e);
				}
			}
		}
		Map<String,Object> params=new HashMap<>();
		JsonObject o=ConverterEditorUtils.converter(obj,JsonObject.class);
		for(String key:o.keySet()) {
			params.put(key, o.get(key));
		}
		if(!CollectionUtils.isEmpty(flexibleFillStrategy)) {
			for(FlexibleFillStrategy<C> fs:flexibleFillStrategy) {
				if(!promptFillList.contains(fs.getName())) {
					continue;
				}
				//缓存已存在则跳过
				if(context.getPromptPlaceholder().containsKey(fs.getName())) {
					continue;
				}
				if(fs.support(context.getClass())) {
					//会替换默认值
					params.put(fs.getName(), fs.invoke(code,context));
				}
			}
		}
		//扩展可走方案2---------后续删除不需要
		if(!CollectionUtils.isEmpty(extendFillStrategy)) {
			Map<String,String> allParams=new HashMap<>();
			for(ExtendFillStrategy<C> efs:extendFillStrategy) {
				for(String fieldName:promptFillList) {
					//缓存已存在则跳过
					if(context.getPromptPlaceholder().containsKey(fieldName)) {
						continue;
					}
					if(allParams.containsKey(fieldName)) {
						params.put(fieldName, allParams.get(fieldName));
					}else if(!params.containsKey(fieldName)) {
						allParams.putAll(efs.invoke(code, prompt, fieldName, context));
						params.put(fieldName, allParams.get(fieldName));
					}
				}
			}
		}
		//Map反射到对象缓存
		return params;
	}
	
	public Object promptInvoke(String fieldName,String code,C context) {
		if(!CollectionUtils.isEmpty(fixedFillStrategy)) {
			for(FixedFillStrategy<C> ps:fixedFillStrategy) {
				if(!ps.getClass().getSimpleName().equalsIgnoreCase(fieldName+FixedFillStrategy.class.getSimpleName())) {
					continue;
				}
				if(!ps.support(context.getClass())) {
					continue;
				}
				return ps.invoke(code,context);
			}
		}
		return null;
	}
	
}
